Table of Contents
들어가는 글
처음 오픈소스 기여를 시도하며 겪은 시행착오를 소개합니다. 대단한 기술적인 내용이 있는 것은 아니고 어떤 시행착오를 거쳐 PR 까지 올렸는지 과정을 담아보겠습니다.
1. 기여할 오픈소스 선정
과거에 오픈소스 컨트리뷰션 아카데미 프로그램에 지원했다가 떨어진 적이 있는데, yorkie 프로젝트에 기여하고 싶었습니다.
현업에서 Go를 활발히 사용하니 자연스레 Go로 개발된 yorkie 프로젝트에 관심을 가진 점도 있지만,
글또에서 처음 큐레이션 된 실시간 협업 애플리케이션 글에서 다룬 CRDT
개념이 yorkie 에 적용되어
있어 더 깊이 알아보고 싶었습니다.
이슈 탐색
먼저 어떤 이슈가 있는지 파악하는 시간을 가졌는데 대부분의 이슈가 활발하게 등록되고 관리되는 것을 보며 프로젝트가 잘 유지되고 있다는 인상을 받았습니다. 다양한 이슈 중 눈에 들어온 것은 gRPC 디펜던시를 제거하고 connectRPC 로 대체하는 작업이었습니다. 사실 connectRPC 가 무엇인지, 왜 yorkie 는 gRPC 대신 connectRPC 를 택했는지 컨텍스트는 몰랐지만 난이도가 높은 이슈는 아닐 것이라 생각했습니다. yorkie codebase 에 이미 connectRPC 가 gRPC 의 대체재로 도입되었지만 여전히 gRPC 관련 코드가 남아있는 상황에서, 해당 이슈의 목표는 gRPC 코드를 제거하는 것이었습니다.
메인테이너가 작성한 이슈 내용을 읽어보니 다른 이슈들과 달리 해야 할 작업의 방향이 명확해 보였습니다. 일단 머리박고 해보자는 생각으로 이슈 할당을 요청했고 빠르게 승인받아 작업을 시작할 수 있었습니다.
2. 삽질하기 싫으면 공식문서 읽자
코드 작업보다 어려운건 프로젝트 세팅이었고, 저는 GPT 와 공식문서, 그리고 구글링까지 적극 활용했습니다.
사실 공식문서를 먼저 읽지 않고 GPT 에게 핑프 한것이 오히려 문제였는데, 삽질에 삽질을 거듭하면서 무언가 잘못되어 가고 있음을 깨달아
다시 공식문서로 되돌아갔습니다. 처음부터 공식문서를 잘 읽었다면 겪지 않아도 될 문제들이었습니다.
예를 들어 yorkie login
cli 명령을 입력하면 config.json 이란 파일이 자동으로 생성되지만, 공식문서를 제대로 읽지 않고
yorkie project create [project-name]
만 실행한 저는 당연히 config.json 이란 파일을 찾을 수 없다는 에러 메시지를 마주했습니다.
'엥? 이런 config 파일도 직접 추가해줘야 하나? 왜 이렇게 불편하게 만들었지?' 생각하며 직접 config.json 에 들어갈 내용을 작성했고,
올바른 경로에 위치시키는 등 불필요한 삽질을 겪었습니다.
이미 눈치채셨겠지만 오픈소스를 만드는 개발자들이 이러한 불편한 프로세스를 그대로 뒀을 리가 없었고,
앞서 얘기한대로 공식문서에 나온 yorkie login
명령어만 잘 입력하면 자동으로 생성되는 파일이었습니다.
yorkie login
을 성공하면 위 처럼 config.json 이 자동으로 생성됩니다.
이런 줄도 모르고 공식문서에 config.json 에 대한 내용을 추가하면 좋겠다고 이슈를 올릴 뻔하기도 했습니다.
3. 무엇을 바꾸었나.
앞서 설명했듯 gRPC 를 connectRPC 로 대체하고 gRPC 디펜던시를 codebase 에서 제거하는 것이 해당 이슈의 목표였습니다.
프로젝트 전체에서 gRPC 의존성을 없애야 한다는 기조가 있었지만, 우선은 이슈 설명에 명시된 create.go
파일부터 작업하는 것을 목표로 했습니다.
기존 코드에서 gRPC 의 흔적은 project create 커맨드에서 에러가 발생했을 때 해당 에러를 converting
하는 메서드였습니다.
에러를 status, error details 등으로 변환하는 gRPC 메서드였는데, connectRPC 에도 비슷한 역할을 하는 함수가 있어 해당 함수로 변경하는 작업을 거쳤습니다.
이슈 설명에는 connectRPC 패키지의 에러를 사용하거나 자체 custom 에러 타입을 생성하라고 나와있었는데, 우선은 첫 번째 방법을 선택했습니다.
기존 코드
err 를 convert 하는 함수가 gRPC 패키지의 메서드로, yorkie 는 gRPC 대신 connectrpc 를 사용하므로 convert 함수를 제거하기로 합니다.
import ( ... "google.golang.org/grpc/status" // dependent on gRPC ) ... project, err := cli.CreateProject(ctx, name) if err != nil { // TODO(chacha912): consider creating the error details type to remove the dependency on gRPC. st := status.Convert(err) for _, detail := range st.Details() { switch t := detail.(type) { case *errdetails.BadRequest: for _, violation := range t.GetFieldViolations() { cmd.Printf("Invalid Fields: The %q field was wrong: %s\n", violation.GetField(), violation.GetDescription()) } } } return err }
변경 코드
기존에는 gRPC 패키지의 메서드를 이용해 에러 상태를 변환했다면, 이제 connectrpc 패키지의 함수로 에러를 컨버팅하여 gRPC 의존성을 제거할 수 있었습니다. 생각보다 개선할 사항이 적어 빠르게 PR 도 올릴 수 있었습니다.
import ( ... "connectrpc.com/connect" // replace with connectRPC ) ... project, err := cli.CreateProject(ctx, name) if err != nil { var connErr *connect.Error if errors.As(err, &connErr) { for _, detail := range connErr.Details() { value, err := detail.Value() if err != nil { continue } badReq, ok := value.(*errdetails.BadRequest) if !ok { continue } for _, violation := range badReq.GetFieldViolations() { cmd.Printf("Invalid Field: %q - %s\n", violation.GetField(), violation.GetDescription()) } } } return err } ...
4. 코드 리뷰 반영
3일 정도 지나서 코드 리뷰 코멘트가 달린 것을 보고 퇴근하자마자 책상에 앉아 리뷰 반영을 시작했습니다.
기존에 올린 커밋은 create.go
파일에서만 gRPC dependency 를 제거했는데 전체 코드베이스로 볼 때 update.go
에도 여전히 gRPC 코드가 남아있어 추가 제거가 필요했습니다.
리뷰어의 코멘트에 따라 애플리케이션 코드 (test 코드 제외) 에서만 종속성을 제거하는 것으로 결정되어 create.go 와 마찬가지로 update.go 도 동일하게 작업을 진행했습니다.
update.go 뿐만 아니라 ci 관련 파일에도 gRPC reference 가 보여 추가적으로 제거했습니다. 다시 리뷰 요청을 하고 답이 오기까지 오매불망 기다리기 힘들어 크로스핏 하러 튀었습니다. 정신없는 와드가 끝나고 메일을 봤는데,, 마침내 merge logo 를 볼 수 있었습니다! 드디어 첫 오픈소스 기여를 할 수 있었습니다.
사실 첫 기여라 엄청 기쁠 줄 알았는데 생각보다 덤덤했습니다. 앞으로도 이렇게 시도하면 되겠구나, 이래서 누구나 컨트리뷰션 할 수 있다고 말하는 것이구나 싶었습니다.
마무리
사실 이슈는 3주 전에 받았지만 작업은 어제 새벽에 시작해서 저녁에 1차 PR을 올리는 것으로 마무리했습니다. 물론 코드리뷰를 받고 수정한 것 까지 생각하면 5일 정도 걸렸습니다. 작업 과정에서 가장 어려웠던 점은 본문에서도 다뤘듯이 프로젝트 세팅과 처음 서버를 실행하는 것이었습니다. 작업 시간의 대부분을 설정 과정에서 삽질하는 데 사용했고, 실제 코드 작업은 생각보다 빨리 끝났습니다.
몇 년째 머릿속으로 생각만 하던 오픈소스 기여가 생각만큼 어려운 일이 아니라는 걸 깨달아, 이 경험을 기록하고 싶었습니다. 또한 공식문서를 제대로 읽어야 한다는 교훈을 몸소 체감할 수 있었고, 까다로운 프로젝트 첫 실행/세팅 과정을 거치며 이런 과정에 점점 익숙해지고 있다는 점에서 조금씩 성장하는 느낌을 받았습니다. 늘 익숙한 코드베이스에서 작업했는데, 오픈소스를 꾸준히 하다보면 다양한 코드와 문제를 더 자주, 그리고 많이 마주할 수 있기에 코드보는 안목도 넓어지지 않을까 생각이 들었습니다.